package com.mew.chess.core.game.qmcs;


import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.mew.chess.core.common.handler.AbstractEnterExitHandler;
import com.mew.chess.core.common.handler.ChessEEAnnotation;
import com.mew.chess.core.common.handler.ChessPushMessageUtil;
import com.mew.chess.core.common.message.request.EnterGameRequestMessage;

import com.mew.chess.core.game.qmcs.game.QmcsGameManager;
import com.mew.chess.core.game.qmcs.game.QmcsRoomManager;
import com.mew.chess.core.game.qmcs.game.QmcsSeatManager;
import com.mew.chess.core.game.qmcs.game.QmcsTableManager;

import com.mew.chess.core.game.qmcs.game.common.QmcsBO;
import com.mew.chess.core.game.qmcs.game.common.QmcsConstantValue;
import com.mew.chess.core.game.qmcs.game.common.QmcsTableUtil;
import com.mew.chess.core.game.qmcs.game.common.QmcsUserBO;
import com.mew.chess.core.game.qmcs.game.message.EnterResponseMessage;
import com.mew.chess.core.game.qmcs.game.message.QmcsCMDMapType;
import com.mew.chess.core.game.qmcs.game.message.QmcsPushMessage;


import com.mew.chess.core.game.qmcs.service.QmcsService;
import com.mew.chess.core.game.shbz.game.common.FishConstantValue;
import com.mew.chess.core.game.shbz.game.common.FishUserBO;
import com.mew.common.dc.redis.UserProfileRedisService;
import com.mew.common.entity.game.WinFree;
import com.mew.common.exception.ResponseCode;
import com.mew.common.rest.bo.GameSession;
import com.mew.common.rest.bo.MewSession;
import com.mew.common.rest.game.ChessEnterRoomResponse;
import com.zebra.remoting.protocol.ZebraCommand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.IntFunction;

@ChessEEAnnotation("QMCS")
@Service
@Slf4j
public class QmcsEEHandler extends AbstractEnterExitHandler {

    @Autowired
    private UserProfileRedisService userProfileRedisService;
    @Autowired
    private QmcsService qmcsService;

    @Override
    public ResponseCode doSitDown(int roomId, GameSession chessSession, MewSession session, boolean isRepeat) {
        //1 校验
        QmcsRoomManager roomManager = QmcsGameManager.getInstance().getController(roomId);
        if (null == roomManager){
            log.error("FishRoomManager roomId {} is null", roomId);
            return ResponseCode.SysException ;
        }

        //2 坐下 tableId,  seatNo 此游戏没有
        QmcsSeatManager seatManager = backSeatCheck(roomManager, session);
        if (isRepeat && null == seatManager){
            log.error("Reconnect seat is null  u:{} ", session.uid);
            return ResponseCode.LoginUn;
        }

        seatManager = null == seatManager ? entityRoomSitDown(roomManager,session.uid) : seatManager;
        if (null == seatManager){
            log.error("EnterRoom RoomFull error: roomId {} , uid {}", roomId, session.toString());
            return ResponseCode.RoomFull;
        }

        chessSession.setTableId(seatManager.getTableId());
        chessSession.setSeatNo(seatManager.getSeatNo());

        return ResponseCode.Success;
    }


    private QmcsSeatManager backSeatCheck(QmcsRoomManager room, MewSession session){
        if (session.rid == -9){
            QmcsTableManager tableManager = room.getTableByUserId(session.uid);
            if (tableManager != null){
                tableManager.exitGameTable(session.uid);
            }
            return null;
        }

        QmcsTableManager table = room.getTable(session.tid);
        if (null == table){
            log.info("Reconnect table is null：roomInout {}", session.toString());
            return null;
        }

        QmcsSeatManager seat = table.getSeatByUserId(session.uid);
        if (null == seat){
            log.info("Reconnect seat is null：roomInout {}", session.toString());
            return null;
        }
        return seat;
    }

    private QmcsSeatManager entityRoomSitDown(QmcsRoomManager roomManager, long userId){
        return entityRoomSitDownRecursion(roomManager, userId, 0);
    }

    private QmcsSeatManager entityRoomSitDownRecursion(QmcsRoomManager roomManager, long userId, int recursionSize){
        List<Integer> emptyTableId = roomManager.emptyTableId();
        if (null == emptyTableId || emptyTableId.isEmpty()){
            QmcsTableUtil.buildTable(roomManager, (QmcsConstantValue.INIT_TABLE_SIZE + recursionSize * 5));
            emptyTableId = roomManager.emptyTableId();
        }

        QmcsTableManager table = roomManager.getTable(emptyTableId.get(RandomUtil.randomInt(0, emptyTableId.size())));
        if (table == null){
            log.error("No Empty table : room {}", roomManager);
            return null;
        }

        List<Integer> emptySeat = table.emptyPlayerSeat();
        Integer seatNo = emptySeat.get(0);
        QmcsSeatManager seat = QmcsTableUtil.sitDown(seatNo, table, userId, table.getSemaphore());

        if (recursionSize > 100){
            log.error("************** Warning *********** Cycle over 100 : room {}", roomManager);
            return null;
        }

        if (null == seat){
            return entityRoomSitDownRecursion(roomManager, userId, recursionSize+1);
        }
        return seat;
    }

    @Override
    public void doFinish(GameSession chessSession, ZebraCommand command, ChessEnterRoomResponse enterRoomResponse)  {
        QmcsRoomManager roomManager = QmcsGameManager.getInstance().getController(chessSession.getRoomId());
        QmcsTableManager tableManager = roomManager.getTable(chessSession.getTableId());
        if (ResponseCode.Success.code() != enterRoomResponse.getErrorState()){
            log.error("Enter room Error uid {} response {}", chessSession.getUserId(), enterRoomResponse.getErrorState());
            tableManager.standUP((byte) chessSession.getSeatNo());
            command.sendFailureCode(enterRoomResponse.getErrorState());
            return;
        }

        QmcsUserBO userBO = tableManager.getOnlineUserMap().get(chessSession.getUserId());
        userBO = null == userBO ? new QmcsUserBO() : userBO;
        userBO.setGameSession(chessSession);
        putWinFree(userBO);
        tableManager.pushOnlineUserMap(userBO);
        //start game
        if (!tableManager.checkIsNoStart()){
            tableManager.startGame();
        }

        EnterResponseMessage enterResponseMessage = buildEnterRoomResponse(userBO, tableManager, roomManager.getBets());
        log.debug("Enter room  {}", enterResponseMessage.toString());
        command.setToken(chessSession.getTk());
        command.sendMessage(enterResponseMessage);
        
        //普通鱼
        QmcsBO[] qmcsBOS = tableManager.getQmcsMap().values().stream().filter(f->f.getRemainStep()<f.getRuleStep()).toArray(new IntFunction<QmcsBO[]>() {
            @Override
            public QmcsBO[] apply(int value) {
                return new QmcsBO[value];
            }
        });

        try {
            TimeUnit.MILLISECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        QmcsPushMessage qmcsPushMessage = QmcsPushMessage.builder().qmcsBOS(qmcsBOS).build();
        ChessPushMessageUtil.pushMessage(chessSession, QmcsCMDMapType.EnterQmcsPushMessage.code(),qmcsPushMessage);

    }



    private EnterResponseMessage buildEnterRoomResponse(QmcsUserBO userBO, QmcsTableManager tableManager, int[] bets){
        EnterResponseMessage response = new EnterResponseMessage();
        response.setBets(bets);
        response.setUserMessage(userBO);
        response.setUserList(tableManager.getOtherPlayer(userBO.getGameSession().getUserId()));

        return response;
    }

    public void putWinFree(QmcsUserBO userBO){
        WinFree winFree = userProfileRedisService.getRedisWinfree(userBO.getUserId(),userBO.getRoomId());
        userBO.setFreeTimes(winFree.getFreeNumber());
        if (userBO.getFreeTimes()>0){
            userBO.setFreeBetId(winFree.getFreeType());
        }

    }


    @Override
    public boolean doExitRoom(MewSession session, int roomId) {
        QmcsTableManager table = QmcsGameManager.getInstance().getController(roomId).getTableByUserId(session.uid);
        QmcsUserBO userBO = table.getOnlineUserMap().get(session.uid);
        qmcsService.doPayment(userBO);
        table.exitGameTable(session.uid);
        return false;
    }




}
